package com.yike.user.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.yike.common.constant.CommonConstant;
import com.yike.common.exception.BusinessException;
import com.yike.common.redis.RedisUtil;
import com.yike.common.tool.*;
import com.yike.common.vo.LoginUserInfoVo;
import com.yike.user.entity.*;
import com.yike.user.mapper.PlatformMenuMapper;
import com.yike.user.mapper.PlatformRoleMapper;
import com.yike.user.mapper.PlatformUserMapper;
import com.yike.user.mapper.PlatformUserRoleMapper;
import com.yike.user.param.PlatformUserLoginParam;
import com.yike.user.param.PlatformUserParam;
import com.yike.user.service.PlatformUserService;
import com.yike.user.param.PlatformUserPageParam;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yike.common.base.BaseServiceImpl;
import com.yike.common.pagination.Paging;
import com.yike.common.pagination.PageInfo;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yike.user.utils.PlatformMenuUtil;
import com.yike.user.vo.PlatformUserVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.UUID;

/**
 * 平台用户 服务实现类
 *
 * @author Sakura
 * @since 2024-10-29
 */
@Slf4j
@Service
public class PlatformUserServiceImpl extends BaseServiceImpl<PlatformUserMapper, PlatformUser> implements PlatformUserService {

    @Autowired
    private PlatformUserMapper platformUserMapper;
    @Autowired
    RedisUtil redisUtil;
    @Autowired
    private PlatformRoleMapper platformRoleMapper;
    @Autowired
    private PlatformUserRoleMapper platformUserRoleMapper;
    @Autowired
    private CommonUtil commonUtil;
    @Autowired
    private PlatformMenuMapper platformMenuMapper;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean savePlatformUser(PlatformUserParam platformUserParam) throws Exception {
        // 校验手机号是否已存在
        PlatformUser platformUser = platformUserMapper.selectOne(Wrappers.<PlatformUser>lambdaQuery()
                .eq(PlatformUser::getMobile, platformUserParam.getMobile()));
        if (platformUser != null) {
            throw new BusinessException("当前手机号已存在，请直接登录");
        }

        platformUser = new PlatformUser();
        BeanUtils.copyProperties(platformUserParam, platformUser);
        platformUser.setCreateBy(LoginUtil.getUserId());
        // 获取用户编号
        platformUser.setUserNo(getNextUserNo());
        // 如果密码为空则将手机号后六位作为密码
        if (StringUtil.isEmpty(platformUserParam.getPassword())) {
            platformUser.setPassword(platformUserParam.getMobile().substring(platformUserParam.getMobile().length() - 6));
        }
        // 加密用户密码
        platformUser.setSalt(SHA256Util.getSHA256Str(UUID.randomUUID().toString()));
        platformUser.setPassword(SHA256Util.getSHA256Str(platformUser.getPassword() + platformUser.getSalt()));
        platformUserMapper.insert(platformUser);

        // 如果角色不为空则保存用户角色信息，目前页面只支持一个角色
        if (platformUserParam.getRoleId() != null) {
            // 保存角色信息
            saveNewUserRole(platformUser.getId(), platformUserParam.getRoleId());
        }

        return true;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean updatePlatformUser(PlatformUserParam platformUserParam) throws Exception {
        // 检查用户是否存在
        PlatformUser platformUser = platformUserMapper.selectById(platformUserParam.getId());
        if (platformUser == null) {
            throw new BusinessException("用户信息异常");
        }

        // 校验修改手机号是否已存在
        Integer checkNum = platformUserMapper.selectCount(Wrappers.<PlatformUser>lambdaQuery()
                .eq(PlatformUser::getMobile, platformUserParam.getMobile())
                .ne(PlatformUser::getId, platformUserParam.getId()));
        if (checkNum > 0) {
            throw new BusinessException("当前手机号已存在");
        }

        // 处理前端传过来的密码是空字符串的情况下其实是不修改密码的
        if (StringUtil.isBlank(platformUserParam.getPassword())) {
            platformUserParam.setPassword(null);
        }

        // 更新基本信息
        BeanUtils.copyProperties(platformUserParam, platformUser);
        platformUser.setUpdateBy(LoginUtil.getUserId());

        // 更新密码（如果不为空）
        if (StringUtil.isNotBlank(platformUserParam.getPassword())) {
            platformUser.setSalt(SHA256Util.getSHA256Str(UUID.randomUUID().toString()));
            platformUser.setPassword(SHA256Util.getSHA256Str(platformUserParam.getPassword() + platformUser.getSalt()));
        }
        platformUserMapper.updateById(platformUser);

        // 更新用户角色
        if (platformUserParam.getRoleId() != null) {
            updatePlatformUserRole(platformUser.getId(), platformUserParam.getRoleId());
        }

        return true;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean deletePlatformUser(Long id) throws Exception {
        return super.removeById(id);
    }

    @Override
    public PlatformUserVo getPlatformUser(Long id) throws Exception {
        return platformUserMapper.getPlatformUserVo(id);
    }

    @Override
    public Paging<PlatformUserVo> getPlatformUserPageList(PlatformUserPageParam platformUserPageParam) throws Exception {
        Page<PlatformUser> page = new PageInfo<>(platformUserPageParam);
        IPage<PlatformUserVo> iPage = platformUserMapper.getPlatformUserList(page, platformUserPageParam);
        return new Paging<PlatformUserVo>(iPage);
    }

    @Override
    public LoginUserInfoVo login(PlatformUserLoginParam platformUserLoginParam) throws Exception {
        // 获取用户真实密码
        //String password = commonUtil.getDecryptStr(platformUserLoginParam.getPassword(), platformUserLoginParam.getSaltKey(), true);

        // 获取当前登录用户信息，这里支持账号和手机号登录
        PlatformUser platformUser = platformUserMapper.selectOne(Wrappers.<PlatformUser>lambdaQuery()
                .nested(wrapper ->
                        wrapper.eq(PlatformUser::getUsername, platformUserLoginParam.getUsername())
                                .or()
                                .eq(PlatformUser::getMobile, platformUserLoginParam.getUsername()))
                .ne(PlatformUser::getDelFlag, 1));
        if (ObjectUtil.isNull(platformUser)) {
            throw new BusinessException(500, "用户名或密码错误");
        }
        // 验证密码是否正确
        if (!platformUser.getPassword().equals(SHA256Util.getSHA256Str(platformUserLoginParam.getPassword() + platformUser.getSalt()))) {
            // 可以在此处添加密码错误冻结机制
            throw new BusinessException(500, "用户名或密码错误");
        }

        // 验证用户状态
        if (platformUser.getStatus() == 2) {
            throw new BusinessException("该账号已被禁用，请联系管理员");
        }
        if (platformUser.getStatus() == 3 || platformUser.getStatus() == 4) {
            throw new BusinessException("该账号已被冻结，请联系管理员");
        }

        if (platformUser.getStatus() != 1) {
            throw new BusinessException("用户状态异常");
        }

        // 更新登录时间
        platformUser.setLoginTime(new Date());
        platformUserMapper.updateById(platformUser);

        // 封装登录用户信息
        LoginUserInfoVo loginUserInfoVo = new LoginUserInfoVo();
        BeanUtils.copyProperties(platformUser, loginUserInfoVo);
        loginUserInfoVo.setType(0);

        // 获取用户角色信息
        PlatformUserRole platformUserRole = platformUserRoleMapper.selectOne(Wrappers.<PlatformUserRole>lambdaQuery()
                .eq(PlatformUserRole::getUserId, platformUser.getId()));
        if (platformUserRole != null) {
            PlatformRole platformRole = platformRoleMapper.selectById(platformUserRole.getRoleId());
            if (platformRole != null) {
                loginUserInfoVo.setRoleId(platformRole.getId());
                loginUserInfoVo.setRoleName(platformRole.getName());
                // 获取用户权限信息，roleId 1为管理员返回所有权限
                List<PlatformMenu> platformMenus;
                List<String> buttonPermissions;
                if (platformRole.getId() == 1) {
                    platformMenus = platformMenuMapper.getPlatformMenus(null);
                    buttonPermissions = platformMenuMapper.getButtonPermissions(null);
                } else {
                    platformMenus = platformMenuMapper.getPlatformMenus(platformRole.getId());
                    buttonPermissions = platformMenuMapper.getButtonPermissions(platformRole.getId());
                }
                loginUserInfoVo.setMenus(PlatformMenuUtil.getLoginMenus(platformMenus));
                loginUserInfoVo.setButtonPermissions(buttonPermissions);
            }
        }

        // 登录成功保存token信息
        String token = UUID.randomUUID().toString();
        loginUserInfoVo.setToken(token);
        // 目前设置为30天有效后面再调
        redisUtil.set(token, loginUserInfoVo, 30 * 24 * 60 * 60);

        // 保存用户登录token，用户修改密码后删除
        LoginUtil.savePlatformUserLoginToken(loginUserInfoVo.getId(), token);

        return loginUserInfoVo;
    }

    // 获取用户编号，注意如果并发很大可以加锁
    private String getNextUserNo() {
        String redisKey = "get_next_user_no";

        if (redisUtil.hasKey(redisKey)) {
            // 如果 Redis 中存在当前编号，则对编号进行自增
            long nextUserNo = redisUtil.incr(redisKey, 1);
            return Long.toString(nextUserNo);
        } else {
            // 如果 Redis 中不存在编号，从数据库获取最大编号
            String maxUserNo = platformUserMapper.getMaxUserNo();

            // 将数据库中获取的最大编号存入 Redis，并返回 +1 的值
            long nextUserNo;
            if (maxUserNo != null && !maxUserNo.isEmpty()) {
                nextUserNo = Long.parseLong(maxUserNo) + 1;
            } else {
                // 如果数据库中没有编号记录，则从默认值 1001 开始
                nextUserNo = 1001;
            }

            // 将初始值存入 Redis
            redisUtil.set(redisKey, nextUserNo);

            return String.valueOf(nextUserNo);
        }
    }

    private void updatePlatformUserRole(Long userId, Long newRoleId) {
        PlatformUserRole platformUserRole = platformUserRoleMapper.selectOne(
                Wrappers.<PlatformUserRole>lambdaQuery().eq(PlatformUserRole::getUserId, userId)
        );

        if (platformUserRole != null) {
            if (!Objects.equals(platformUserRole.getRoleId(), newRoleId)) {
                platformUserRoleMapper.deleteById(platformUserRole.getId());
                saveNewUserRole(userId, newRoleId);
            }
        } else {
            saveNewUserRole(userId, newRoleId);
        }
    }

    private void saveNewUserRole(Long userId, Long roleId) {
        // 先判断角色是否存在
        PlatformRole platformRole = platformRoleMapper.selectById(roleId);
        if (platformRole == null) {
            throw new BusinessException("角色信息异常");
        }
        PlatformUserRole newPlatformUserRole = new PlatformUserRole();
        newPlatformUserRole.setUserId(userId);
        newPlatformUserRole.setRoleId(roleId);
        newPlatformUserRole.setCreateBy(LoginUtil.getUserId());
        platformUserRoleMapper.insert(newPlatformUserRole);
    }

}
